package cc.kigh.user.service.impl;

import cc.kigh.common.constant.Constants;
import cc.kigh.common.constant.SessionConstants;
import cc.kigh.common.core.domain.PageQuery;
import cc.kigh.common.core.mybatisplus.core.ServicePlusImpl;
import cc.kigh.common.core.page.TableDataInfo;
import cc.kigh.common.utils.Asserts;
import cc.kigh.common.utils.BeanCopyUtils;
import cc.kigh.common.utils.StringUtils;
import cc.kigh.user.domain.bo.UmsUserBo;
import cc.kigh.user.domain.vo.ClientUserVo;
import cc.kigh.user.domain.vo.UmsUserVo;
import cc.kigh.user.mapper.UmsUserMapper;
import cc.kigh.user.message.UserMessage;
import cc.kigh.user.service.IUmsUserService;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cc.kigh.user.domain.UmsUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 用户Service业务层处理
 *
 * @author ruoyi
 * @date 2022-02-17
 */
@Service
public class UmsUserServiceImpl extends ServicePlusImpl<UmsUserMapper, UmsUser, UmsUserVo> implements IUmsUserService {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public UmsUserVo queryById(Long cid) {
        return getVoById(cid);
    }

    @Override
    public TableDataInfo<UmsUserVo> queryPageList(UmsUserBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<UmsUser> lqw = buildQueryWrapper(bo);
        Page<UmsUserVo> result = pageVo(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public List<UmsUserVo> queryList(UmsUserBo bo) {
        LambdaQueryWrapper<UmsUser> lqw = buildQueryWrapper(bo);
        return listVo(lqw);
    }

    private LambdaQueryWrapper<UmsUser> buildQueryWrapper(UmsUserBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<UmsUser> lqw = Wrappers.lambdaQuery();
        lqw.like(bo.getCname() != null, UmsUser::getCname, bo.getCname());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), UmsUser::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getPassword()), UmsUser::getPassword, bo.getPassword());
        lqw.eq(bo.getStatus() != null, UmsUser::getStatus, bo.getStatus());
        return lqw;
    }

    @Override
    public Boolean insertByBo(UmsUserBo bo) {
        UmsUser add = BeanUtil.toBean(bo, UmsUser.class);
        validEntityBeforeSave(add);
        boolean flag = save(add);
        if (flag) {
            bo.setCid(add.getCid());
        }
        return flag;
    }

    @Override
    public Boolean updateByBo(UmsUserBo bo) {
        UmsUser update = BeanUtil.toBean(bo, UmsUser.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(UmsUser entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    @Override
    public SaLoginModel login(UmsUserBo bo) {

        UmsUser user = lambdaQuery().eq(UmsUser::getPhone, bo.getPhone())
            .one();
        Asserts.notNull(user, UserMessage.USERNAME_PASSWORD_ERROR);

        // 密码校验
        Asserts.isTrue(bCryptPasswordEncoder.matches(bo.getPassword(), user.getPassword()), UserMessage.USERNAME_PASSWORD_ERROR);
        SaLoginModel loginModel = SaLoginModel.create()
            .setDevice("H5")
            .build();
        StpUtil.login(user.getCid(), loginModel);
        loginModel.setToken(StpUtil.getTokenValue());

        StpUtil.getSession().set(SessionConstants.LOGIN_USER_INFO, BeanCopyUtils.copy(user, ClientUserVo.class));
        return loginModel;
    }

    @Override
    public boolean logout() {
        StpUtil.logout();
        return true;
    }

    @Override
    public boolean registry(UmsUserBo bo) {
        boolean exists = lambdaQuery()
            .eq(UmsUser::getPhone, bo.getPhone())
            .select(UmsUser::getPhone)
            .last(Constants.LIMIT_1)
            .exists();
        Asserts.isFalse(exists, UserMessage.USER_HAVE_EXIST);
        UmsUser umsUser = new UmsUser();
        umsUser.setCid(IdWorker.getId());
        umsUser.setCname(bo.getCname());
        umsUser.setPhone(bo.getPhone());
        umsUser.setPassword(bCryptPasswordEncoder.encode(bo.getPassword()));
        umsUser.setStatus(1);
        return save(umsUser);
    }
}
